#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
#include "texture.h"


int mtextures=256;
int ntextures;
GLuint textures[256];

/*ritorna l'id della texture caricata*/
GLuint caricaTexture(char* filename){
GLuint textureid=(GLuint)-1;


	#define LINE_WIDTH 1024

	FILE *f; // puntatore al file
	char temp[LINE_WIDTH]; //array temporaneo che conterra' una riga di file
	char img_type; // temporary storage
	int txwidth, txheight;// dimensioni della texture
	unsigned char * txdata; // la texture vera e propria
	int val;
	int i = 0;
	int step = 0;


/*	do fgets(temp,100,f);while (temp[0]=='#'); 
   img_type = temp[1]; // Store the type

	do fgets(temp,100,f);while (temp[0]=='#'); 
	sscanf(temp,"%d %d",&texwidth,&texheight); // Store Dimensions
*/

	if ((f = fopen(filename, "rt")) == NULL)  {
    	printf("Non posso aprire il file %s \n",filename);
      	exit(1);
	}else{
		printf("ho aperto il file %s \n", filename);
	}
	// presumo che il file ppm abbia uno schema fissato che puo' presentare al max 3 gruppi
	// di commenti
	do {
		fgets(temp,100,f);// leggi 100 char dal puntatore f
	}while(temp[0]=='#'); //finche' non incontri un cancelletto
 	img_type = temp[1]; // quello che hai letto e hai in temp[1] e' il tipo di ppm
 //	printf("tipo file %s \n", img_type);
	do {
		fgets(temp,100,f);// leggi 100 char dal puntatore f
	}while(temp[0]=='#'); //finche' non incontri un cancelletto
	sscanf(temp,"%d %d",&txwidth,&txheight); // xche' c'e' l'&???
 	/*la sscanf legge da input come la scanf pero' l'input e' un puntatore in questo caso temp
	 * ha un input formattato come la printf quindi con i %d posiziono i marker per le variabili 
	 * di destinazione esplicitate dopo*/
	do {
		fgets(temp,100,f);// leggi 100 char dal puntatore f
	}while(temp[0]=='#'); //finche' non incontri un cancelletto
	/*a questo punto ho davanti a me solo i dati della texture vera e propria*/
	txdata = (char*)malloc(sizeof(char) * txwidth * txheight * 3);
	/*devo allocare la memoria necessaria a contenere i dati della texture quindi richiedo 
	 * uno spazio pari alla grandezza di un char moltiplicato per le dimensioni della texture
	 * moltiplicato per 3 che e' il numero di colori usati per definirla (RGB)*/
	 if (img_type == '6'){ // non e' in ASCII, quindi uso la lettura per file binari
	 	printf("NON E' un file ascii \n");
		int imagesize=3*txwidth*txheight;
		int remaining=imagesize;
		int cont=0;

		while (remaining)
		{
			int nread=fread(txdata+cont,1,remaining,f);
			remaining-=nread;
			cont     +=nread;
		}

		if (cont!=imagesize)
		{
			printf("error reading file\n");
			exit(-1);
		}
/*   size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 
     La funzione fread() legge da stream nmemb elementi, ciascuno di dimensione size.
     Gli elementi letti vengono immagazzinati nel buffer puntato da ptr 
     che deve essere di dimensioni adeguate.
     Quindi txdata e' il ptr di destinazione dei dati di dimensione char * 3 perche' in RGB 
     gli elementi letti sono esattamente txwidth*txheight e vengono letti da f
*/
	 }else if (img_type == '3' ){//e' un file ASCII
	 	for( i = 0; i< 3 * txwidth * txheight; i++ ){
	 		fscanf(f,"%d",&val);//come la sscanf ma avviene da stream quindi da file
	 		txdata[i] = val;
	 	}
	 }  else 
	 exit(0); // cant read other PNMs
	 fclose(f);
	glGenTextures(1,&textureid);
	glBindTexture(GL_TEXTURE_2D, textureid);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, txwidth, txheight, GL_RGB, GL_UNSIGNED_BYTE, txdata);
	free(txdata);

	return textureid;
}


void initTextures(void){
	
		textures[TX_FLOOR_S1]=caricaTexture("texture/floor1.ppm");
		textures[TX_CEILING_S1]=caricaTexture("texture/ceiling1.ppm");
		textures[TX_WALL_S1]=caricaTexture("texture/wall1.ppm");
		
		textures[TX_FLOOR_S2]=caricaTexture("texture/floor2.ppm");
		textures[TX_CEILING_S2]=caricaTexture("texture/ceiling2.ppm");
		textures[TX_WALL_S2]=caricaTexture("texture/wall2.ppm");
		
		textures[TX_FLOOR_S3]=caricaTexture("texture/floor3.ppm");
		textures[TX_CEILING_S3]=caricaTexture("texture/ceiling3.ppm");
		textures[TX_WALL_S3]=caricaTexture("texture/wall3.ppm");
		
		textures[TX_FLOOR_S4]=caricaTexture("texture/floor4.ppm");
		textures[TX_CEILING_S4]=caricaTexture("texture/ceiling4.ppm");
		textures[TX_WALL_S4]=caricaTexture("texture/wall4.ppm");
		
		textures[TX_FLOOR_S5]=caricaTexture("texture/floor5.ppm");
		textures[TX_CEILING_S5]=caricaTexture("texture/ceiling5.ppm");
		textures[TX_WALL_S5]=caricaTexture("texture/wall5.ppm");

		textures[TX_DOOR_1]=caricaTexture("texture/l1.png.ppm");
		textures[TX_DOOR_2]=caricaTexture("texture/a2.png.ppm");
		textures[TX_DOOR_3]=caricaTexture("texture/l1.png.ppm");
		textures[TX_DOOR_4]=caricaTexture("texture/a2.png.ppm");
		textures[TX_TORRETTA_1]=caricaTexture("texture/torretta1.ppm");
		textures[TX_COCACOLA]=caricaTexture("texture/coca-cola.ppm");
		textures[TX_POSTER1]=caricaTexture("texture/doom.ppm");
		textures[TX_CORNICE]=caricaTexture("texture/q1.png.ppm");
		textures[TX_POSTER2]=caricaTexture("texture/poster2.ppm");
		textures[TX_POSTER3]=caricaTexture("texture/poster3.ppm");
		textures[TX_POSTER4]=caricaTexture("texture/poster4.ppm");
		textures[TX_POSTER5]=caricaTexture("texture/poster5.ppm");
		textures[TX_POSTER6]=caricaTexture("texture/poster6.ppm");
		textures[TX_PANNELLO1]=caricaTexture("texture/pannello1.ppm");
		textures[TX_PANNELLO2]=caricaTexture("texture/pannello2.ppm");
		textures[TX_DRAGO]=caricaTexture("texture/drago.ppm");
		textures[TX_COCAPEPSI]=caricaTexture("texture/cokepepsi.ppm");
		textures[TX_PAVIMENTOEXT]=caricaTexture("texture/z1.png.ppm");
		textures[TX_POSTER7]=caricaTexture("texture/poster7.ppm");
		textures[TX_POSTER8]=caricaTexture("texture/poster8.ppm");
		textures[TX_POSTER9]=caricaTexture("texture/poster9.ppm");
		textures[TX_DOORSIDE]=caricaTexture("texture/v1.png.ppm");
		
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
	
}

void applyTexture(int curtexture){
		glBindTexture(GL_TEXTURE_2D,textures[curtexture]);
}




